home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 16.7 KB | 563 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: ClockFra.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: © 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef CLOCKFRA_H
- #include "ClockFra.h"
- #endif
-
- #ifndef CLOCKPAR_H
- #include "ClockPar.h"
- #endif
-
- #ifndef CLOCKDEF_H
- #include "ClockDef.h"
- #endif
-
- // ----- Part Layer -----
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- // ----- OS Layer -----
-
- #ifndef FWTXTSHP_H
- #include "FWTxtShp.h"
- #endif
-
- #ifndef FWRECSHP_H
- #include "FWRecShp.h"
- #endif
-
- #ifndef FWLINSHP_H
- #include "FWLinShp.h"
- #endif
-
- #ifndef FWOVLSHP_H
- #include "FWOvlShp.h"
- #endif
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- #ifndef FWTXTBOX_H
- #include "FWTxtBox.h"
- #endif
-
- #ifndef FWCFMRES_H
- #include "FWCFMRes.h"
- #endif
-
- #ifndef FWRESACC_H
- #include "FWResAcc.h"
- #endif
-
- #ifndef FWRESTYP_H
- #include "FWResTyp.h"
- #endif
-
- #ifndef FWFXMATH_H
- #include "FWFxMath.h"
- #endif
-
- //========================================================================================
- // RunTime information
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odfclock
- #endif
-
- FW_DEFINE_CLASS_M1 (CClockFrame, FW_CFrame)
-
- //========================================================================================
- // Constants
- //========================================================================================
-
- const FW_CFixed kClockRadius = FW_IntToFixed(100); // In logical units
- const FW_CFixed kFxPI = FW_DoubleToFixed(3.1415926);
-
- //========================================================================================
- // class CClockFrame
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::CClockFrame
- //----------------------------------------------------------------------------------------
-
- CClockFrame::CClockFrame(Environment* ev, ODFrame* odFrame, FW_CPresentation* presentation, CClockPart* clockPart) :
- FW_CFrame(ev, odFrame, presentation, clockPart),
- fMapping(FW_kCustomConstrained)
- {
- fClockPart = clockPart;
-
- // ----- Load the face string ("OpenDoc") -----
- {
- FW_CSharedLibraryResourceFile resFile;
- ::FW_LoadStringByID(resFile, kClockFaceStrings, MULTISTRINGRES, kClockOpenDocString, fFaceString);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::~CClockFrame
- //----------------------------------------------------------------------------------------
-
- CClockFrame::~CClockFrame()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::FacetAdded
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::FacetAdded(Environment* ev, ODFacet* facet)
- {
- FW_CFrame::FacetAdded(ev, facet);
-
- // ----- First reset the mapping. Because ResetMapping needs the window
- // ----- we have to wait for FacetAdded before calling ResetMapping the first time
- this->ResetMapping(ev);
-
- // ----- Calculate a default rectangle size for a digital clock
- FW_CFacetContext fc(ev, facet, NULL);
-
- FW_CString32 digitalString;
- {
- FW_CSharedLibraryResourceFile resFile;
- ::FW_LoadStringByID(resFile, kClockFaceStrings, MULTISTRINGRES, kClockDigitalWidthString, digitalString);
- }
-
- FW_CTextShape textShape(
- digitalString,
- FW_IntToFixed(0),
- FW_IntToFixed(0),
- FW_PFont(FW_kTimes, FW_kPlain, FW_IntToFixed(12)),
- FW_kTextAlignLeft | FW_kTextAlignBaseLine);
-
- textShape.GetBounds(fc, fDigitalClockRect);
-
- fDigitalClockRect.Inset(FW_IntToFixed(-3), FW_IntToFixed(-3));
-
- this->UpdateUsedAndActiveShapes(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::ChangeClockType
- //----------------------------------------------------------------------------------------
- // If I switch to analog and my frame is smaller than ff(80) try to request something bigger
-
- void CClockFrame::ChangeClockType(Environment* ev, short newClockType)
- {
- if (!IsTopFrame(ev) && newClockType == kAnalogClock)
- {
- FW_CRect frameBounds = GetBounds(ev);
- FW_CFixed height = frameBounds.Height();
- FW_CFixed width = frameBounds.Width();
- FW_CFixed min = FW_Minimum(height, width);
-
- if (min < FW_IntToFixed(80))
- {
- FW_CAcquiredODShape askedShape = ::FW_NewODShape(ev, FW_CRect(FW_kZeroPoint, FW_IntToFixed(80), FW_IntToFixed(80)));
- this->RequestFrameShape(ev, askedShape);
- }
- }
-
- UpdateUsedAndActiveShapes(ev);
- ResetMapping(ev);
- Invalidate(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::AdjustUsedShape
- //----------------------------------------------------------------------------------------
- // 'suggestedUsedShape' is equal to the frame shape
-
- ODShape* CClockFrame::AdjustUsedShape(Environment* ev, ODShape* suggestedUsedShape)
- {
- FW_CRect usedRect = FW_GetShapeBoundingBox(ev, suggestedUsedShape);
-
- ODShape* newUsedShape;
- if (fClockPart->GetClockType() == kAnalogClock)
- {
- FW_CRect rect(usedRect);
- FW_CFixed height = usedRect.Height();
- FW_CFixed width = usedRect.Width();
-
- if (height < width)
- rect.right = rect.left + height;
- else
- rect.bottom = rect.top + width;
- rect.PlaceInCenter(usedRect);
-
- newUsedShape = ::FW_CreateOvalODShape(ev, rect);
- }
- else
- {
- FW_CRect rect(fDigitalClockRect);
- rect.PlaceInCenter(usedRect);
-
- newUsedShape = ::FW_NewODShape(ev, rect);
- }
-
- return newUsedShape;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::AdjustActiveShape
- //----------------------------------------------------------------------------------------
- // [HLX] Because OpenDoc uses the Frame shape as the default active shape I need to
- // adjust my active shape too.
-
- ODShape* CClockFrame::AdjustActiveShape(Environment* ev, ODFacet* facet, ODShape* suggestedActiveShape)
- {
- suggestedActiveShape->Acquire(ev);
- return suggestedActiveShape;
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::FrameShapeChanged
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::FrameShapeChanged(Environment* ev)
- {
- FW_CFrame::FrameShapeChanged(ev);
-
- this->ResetMapping(ev);
-
- this->Invalidate(ev); // Invalidate frame shape
- this->GetODFrame(ev)->InvalidateActiveBorder(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateClock(Environment* ev, const FW_CTime& time)
- {
- FW_CFrameFacetIterator facets(ev, this);
- for (ODFacet* clockFacet = (ODFacet*)facets.First(ev); facets.IsNotComplete(ev); clockFacet = (ODFacet*)facets.Next(ev))
- {
- FW_CFacetContext fc(ev, clockFacet);
-
- if (fClockPart->GetClockType() == kAnalogClock)
- {
- fc.SetMapping(fMapping);
- UpdateAnalogClock(ev, fc, time);
- }
- else
- UpdateDigitalClock(ev, fc, time);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::Draw
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::Draw(Environment* ev, ODFacet* odFacet, ODShape* invalidShape)
- {
- FW_CFacetContext fc(ev, odFacet, invalidShape);
-
- // [HLX] This will be moved into an erase adorner
- if (IsRoot(ev))
- {
- FW_CRect invalidRect;
- fc.GetClipRect(invalidRect);
-
- #ifdef FW_BUILD_MAC
- FW_PInk ink(FW_kRGBWhite,
- FW_kRGBWhite,
- FW_kErase);
- #else
- FW_PInk ink(FW_CColor(::GetSysColor(COLOR_WINDOWTEXT), 0),
- FW_CColor(::GetSysColor(COLOR_APPWORKSPACE), 0),
- FW_kErase);
- #endif
- FW_CRectShape::RenderRect(fc, invalidRect, FW_kFill, ink);
- }
-
- FW_CTime lastTime = fClockPart->GetLastTime();
-
- if (fClockPart->GetClockType() == kAnalogClock)
- {
- fc.SetMapping(fMapping);
-
- this->DrawClockFace(ev, fc);
-
- this->DrawSecondHand(ev, fc, FW_IntToFixed(lastTime.GetSecond()));
- this->DrawMinuteHand(ev, fc, FW_IntToFixed(lastTime.GetMinute()));
- this->DrawHourHand(ev, fc, FW_IntToFixed(lastTime.GetHour()), FW_IntToFixed(lastTime.GetMinute()));
- }
- else
- UpdateDigitalClock(ev, fc, lastTime);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawClockFace
- //----------------------------------------------------------------------------------------
-
- static void DrawTicks(FW_CFacetContext& fc, FW_CLineShape& lineShape,
- FW_CFixed xStart, FW_CFixed yStart,
- FW_CFixed xEnd, FW_CFixed yEnd)
- {
- lineShape.SetLineStart(xStart, yStart);
- lineShape.SetLineEnd(xEnd, yEnd);
- lineShape.Render(fc);
-
- lineShape.SetLineStart(-xStart, yStart);
- lineShape.SetLineEnd(-xEnd, yEnd);
- lineShape.Render(fc);
-
- lineShape.SetLineStart(xStart, -yStart);
- lineShape.SetLineEnd(xEnd, -yEnd);
- lineShape.Render(fc);
-
- lineShape.SetLineStart(-xStart,-yStart);
- lineShape.SetLineEnd(-xEnd, -yEnd);
- lineShape.Render(fc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::ResetMapping
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::ResetMapping(Environment* ev)
- {
- FW_CPoint logicalExtent(kClockRadius.MultipliedByInt(2), kClockRadius.MultipliedByInt(2));
- FW_CPoint deviceExtent = GetExtent(ev);
-
- fMapping.SetExtents(ev, logicalExtent, deviceExtent);
- fMapping.SetDeviceOrigin(ev, deviceExtent.x.Half(), deviceExtent.y.Half());
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawClockFace
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawClockFace(Environment* ev, FW_CFacetContext& fc)
- {
- // ----- Erase under the clock -----
- FW_CRect ovalRect(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
-
- FW_COvalShape::RenderOval(
- fc,
- ovalRect,
- FW_kFill,
- FW_kWhiteEraseInk);
-
- FW_COvalShape::RenderOval(
- fc,
- ovalRect,
- FW_kFrame,
- FW_kNormalInk,
- FW_PStyle(FW_IntToFixed(2)));
-
- // ----- Render the "OpenDoc" string -----
- FW_CTextShape::RenderText(
- fc,
- fFaceString,
- FW_CPoint(FW_IntToFixed(0), -kClockRadius.Half()),
- FW_PFont(FW_kHelvetica, FW_kItalic, kClockRadius.DividedByInt(5)),
- FW_kTextAlignHCenter | FW_kTextAlignBaseLine);
-
- // Use the symmetry of the clock face to speed up the calculations for drawing the face
- // We only need to calculate points for 45 degrees of the circle. The remaining points can
- // be inferred from these points
-
- short angle = 0;
- short fiveMinute = 0;
-
- FW_PStyle lineStyle = FW_ODFixedToFixed(0x00008000); // 1/2
- FW_CLineShape lineShape;
- lineShape.SetStyle(lineStyle);
-
- FW_CFixed xStart, yStart, xEnd, yEnd;
-
- FW_CFixed radius = kClockRadius - FW_IntToFixed(2); // 2 logical unit
- while (angle < 45)
- {
- // ----- convert angle to radians -----
- FW_CFixed radians = (kFxPI * FW_IntToFixed(90 - angle)).DividedByInt(180);
- FW_CFixed cosRadian = radians.Cos();
- FW_CFixed sinRadian = radians.Sin();
-
- xStart = radius * cosRadian;
- yStart = radius * sinRadian;
-
- FW_CFixed tickRadius;
- if (fiveMinute == 0)
- {
- tickRadius = radius - radius.DividedByInt(10);
- fiveMinute = 4;
- }
- else
- {
- tickRadius = radius - radius.DividedByInt(20);
- fiveMinute--;
- }
-
- xEnd = tickRadius * cosRadian;
- yEnd = tickRadius * sinRadian;
-
- DrawTicks(fc, lineShape, xStart, yStart, xEnd, yEnd);
-
- DrawTicks(fc, lineShape, yStart, xStart, yEnd, xEnd);
-
- angle += 6;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CalcPoint
- //----------------------------------------------------------------------------------------
-
- static FW_CPoint CalcPoint(FW_CFixed radius, FW_CFixed angle)
- {
- FW_CPoint point(
- radius * angle.Sin(),
- - radius * angle.Cos());
-
- return point;
- }
-
- //----------------------------------------------------------------------------------------
- // ::DegreesToRadians
- //----------------------------------------------------------------------------------------
-
- static inline FW_CFixed DegreesToRadians(FW_CFixed degrees)
- {
- return (degrees * kFxPI).DividedByInt(180);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawHourHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawHourHand(Environment* ev,
- FW_CFacetContext& fc,
- FW_CFixed hour,
- FW_CFixed minute)
- {
- FW_CFixed hourRadius = kClockRadius.DividedByInt(2); // Make the hour hand short and stubby
-
- if (hour > FW_IntToFixed(11))
- hour -= FW_IntToFixed(12);
-
- // ----- Divide the clock face into degrees.
- // ----- Hour hand falls on every five minutes or every 30 degrees
- FW_CFixed radians = ::DegreesToRadians(hour.MultipliedByInt(30) + minute.Half());
-
- FW_CPoint newPoint = ::CalcPoint(hourRadius, radians);
-
- FW_PStyle style(FW_IntToFixed(3));
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.SetStyle(style);
- lineShape.Render(fc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawMinuteHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawMinuteHand(Environment* ev,
- FW_CFacetContext& fc,
- FW_CFixed minute)
- {
- FW_CFixed minuteRadius = kClockRadius * FW_DoubleToFixed(0.8); // Make the minute hand longer than the hour hand
-
- // ----- Divide the clock face into degrees.
- // ----- (360 degrees divided by 60 minutes is 6 degrees per minute)
- FW_CFixed radians = ::DegreesToRadians(minute.MultipliedByInt(6));
-
- FW_CPoint newPoint = ::CalcPoint(minuteRadius, radians);
-
- FW_PStyle style(FW_IntToFixed(2));
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.SetStyle(style);
- lineShape.Render(fc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::DrawSecondHand
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::DrawSecondHand(Environment* ev,
- FW_CFacetContext& fc,
- FW_CFixed second)
- {
- FW_CFixed secondRadius = kClockRadius * FW_DoubleToFixed(0.9); // A nice sweeping second hand
-
- // ----- Divide the clock face into degrees.
- // ----- (360 degrees divided by 60 seconds is 6 degrees per second)
- FW_CFixed radians = ::DegreesToRadians(second.MultipliedByInt(6));
-
- FW_CPoint newPoint = ::CalcPoint(secondRadius, radians);
-
- FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
- lineShape.SetInk(FW_kInvertInk);
- lineShape.Render(fc);
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateAnalogClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateAnalogClock(Environment* ev,
- FW_CFacetContext& fc,
- const FW_CTime& time)
- {
- FW_CTime lastTime = fClockPart->GetLastTime();
-
- // ----- Since we're called every second go ahead and update the second hand
- this->DrawSecondHand(ev, fc, FW_IntToFixed(lastTime.GetSecond()));
- this->DrawSecondHand(ev, fc, FW_IntToFixed(time.GetSecond()));
-
- if (lastTime.GetMinute() != time.GetMinute())
- {
- this->DrawMinuteHand(ev, fc, FW_IntToFixed(lastTime.GetMinute()));
- this->DrawMinuteHand(ev, fc, FW_IntToFixed(time.GetMinute()));
-
- this->DrawHourHand(ev, fc, FW_IntToFixed(lastTime.GetHour()), FW_IntToFixed(lastTime.GetMinute()));
- this->DrawHourHand(ev, fc, FW_IntToFixed(time.GetHour()), FW_IntToFixed(time.GetMinute()));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CClockFrame::UpdateDigitalClock
- //----------------------------------------------------------------------------------------
-
- void CClockFrame::UpdateDigitalClock(Environment* ev,
- FW_CFacetContext& fc,
- const FW_CTime& time)
- {
- FW_CString255 timeString;
- time.GetTimeString(timeString, TRUE);
-
- FW_CAcquiredODShape aqUsedShape(this->AcquireUsedShape(ev, NULL));
- FW_CRect usedShapeRect = FW_GetShapeBoundingBox(ev, aqUsedShape);
-
- FW_CRectShape rectShape(usedShapeRect, FW_kFill);
- rectShape.SetInk(FW_kWhiteEraseInk);
- rectShape.Render(fc);
-
- rectShape.SetRenderVerb(FW_kFrame);
- rectShape.Render(fc);
-
- FW_CString32 fontName(FW_kSystemFont);
- FW_PFont fontStyle(fontName, FW_kPlain, FW_IntToFixed(12));
- FW_CTextBoxShape::RenderTextBox(fc, timeString, usedShapeRect, fontStyle, FW_kTextBoxJustifyHCenter);
- }
-
-